.\" Michael P. Reilly (C) 2012-2015  All rights reserved
.\" sshcmd.man $RelNo$  $Revision$
.\" Process this file with
.\" groff -man -Tascii sshcmd.1
.\"
.TH sshcmd 1 "August 2013" GNU/Python "User Manuals"
.SH NAME
sshcmd \- parallel remote execution
.SH SYNOPSYS
.B sshcmd
.BI [ options ]
.I rmtcmd
.P
.B sshcmd
.BI [ options ]
.BI --remdir= remdir
.IB lclfiles ...
.P
.B sshcpy
.BI [ options ]
.IB lclfiles ...
.I remdir
.SH DESCRIPTION
.B sshcmd
reads a list of SSH hostames and spawns remote commands then displays
the output of each.
.P
By default,
.B sshcmd
will read a list of hostnames from stdin, one per line, the format of the line is:
.RS
.IR [username@] hostname " [comment]
.RE
The first field is taken as a [user@]hostname as in
.BR ssh (1).
The comment is included in the output.
For example:
.RS
.nf
localhost
appserver@remote
jenkins@buildserver jenkins server
.fi
.RE
Instead of reading from stdin, the
.B \-\-file
argument can be used.  Or for just a small finite number, use
.BR \-\-remote .
.P
A thread pool is created (see --poolsize below) to run remote operations in
parellel.
For large amounts being transferred, it is not beneficial to have a large pool.
Because operations are in parellel,
output is only displayed/dumped when all have finished.
Stopping the program (Ctrl-Z) will pause the execution
and show the accumulated output to that point.
Aborting the program (Ctrl-C) will terminate the program
and show the accumulated output to that point.
.P
The second and third envocations are the same.
Instead of executing commands, files locally are copied to the
.I remdir
on the remote server.
The same remote directory must exist on each directory.
.P
OpenSSH options automatically used are:
BatchMode=yes,
.RI ConnectTimeout= timeout ,
ForwardAgent=no, ForwardX11=no,
GSSAPIAuthentication=no, LogLevel=ERROR, PasswordAuthentication=no,
StrictHostKeyChecking=no.
In addition, in sshcpy mode, the arguments '-Brp' are given.
.P
When dumping to a log directory, output from each
.IR [user@] host
will be stored in the format:
.RS
.nf
.RI "returncode: " rc
stdout:
.I "output with leading tabs
stderr:
.I "output with leading tabs
.fi
.RE
Stdout and stderr can be retrieved using:
.nf
.RI "$ sed -ne '/stdout:/,/stderr:/{;/^\et/s///p;}' " logdir/hostname
.fi
and
.nf
.RI "$ sed -ne '/stderr:/,${;/^\et/s///p;}' " logdir/hostname
.fi
respectively.
.P
To just show the output of the failed calls, use
.B --show=failure
or just
.BR "-s f" .
To show just the successful calls, use
.B --show=success
or just
.BR "-s succ" .
.P
Operational statistics can be seen at the end of the program execution with
the
.B \-\-showstats
option.  Standard statistics are shown including duration, cumulative duration,
(approximate) time saved (percentage), average visit time, etc.
Viewing the statistics output can help tune the poolsize parameter.
.P
Default output during execution shows when starting a call to a host and when the call has finished (with the return code).
.RS
.nf
$ sshcmd --remote=localhost true
spawning me@localhost
reclaiming me@localhost rc = 0
=me@localhost=0

.fi
.RE
.SH OPTIONS
.TP
.B --help, -h
show usage/options and exit
.TP
.B --version
show version information and exit
.TP
.BI "\-\-file=" listfilename ", \-f " listfilename
list of SSH hostnames to use instead of stdin
.TP
.B --quiet, -q
very list output
.TP
.B --verbose, -v
normal output
.TP
.BI "\-\-input=" inputfile ", \-I " inputfile
file to upload to each server; equivalent of stdin to
.BR ssh (1)
.TP
.BI "\-\-keyfile=" privkey ", \-K " privkey
SSH private key
.TP
.BI "\-\-poolsize=" poolsize ", \-p " poolsize
size of the thread pool, defaults to 10
.TP
.BI "\-\-remdir=" remdir ", \-R " remdir
remote directory for sshcpy
.TP
.BI "\-\-show=" output ", \-s " output
restrict response based on exit status; acceptable values are 'all',
\'a', 'success', 'succ', 's', 'failure', 'fail', 'f';
default is 'all'
.TP
.BI "\-\-remote=" userhost ", \-r " userhost
explicitly specify hosts instead of input, may be use multiple times
.TP
.B \-\-showstats, \-S
show statistics
.TP
.B \-\-pipeout, \-P
simple output for piping; no rmtcmd output. Output is same format as input
including comment, except current username is added where none is used.
Best when used with \-\-show option.
.TP
.BI "\-\-logdir=" dir ", \-L " dir
dump output to directory; each hostname in
.I input
will have the return code, stdout and stderr dumped to a file named
after the hostname
.TP
.BI "\-\-timeout=" seconds ", \-T " seconds
change default ConnectTimeout
.SH EXIT STATUS
.IP 0
Normal operation.
.IP 1
Error; see output.
.SH SIGNALS
.IP "SIGTSTP (Ctrl-Z)
Pause the program including any remote calls; show accumulated output.
.IP "SIGINT (Ctrl-C)
Abort the program including any remote calls; show accumulated output.
.SH FILES
.IP $HOME/.sshcmd.cfg
Configuration file for
.BR sshcmd .
Format is a Python dict value.
.IP $HOME/.sshcpy.cfg
Configuration file for
.BR sshcpy .
Format is a Python dict value.
.SH ENVIRONMENT
.IP DEBUG
Enable debugging mode.
.IP HOME
Default directory of configuration files.
.IP TMPDIR
Defaults to
.IR "/var/tmp" .
.SH DIAGNOSTICS
Set the DEBUG environment variable to a non empty string value, for example,
.BR "'DEBUG=1'" .
.SH BUGS
.P
Does not currently work under Python 3.x.
.P
There is currently nothing to increase the verbosity of
the OpenSSH calls through
.B sshcmd
using command-line options or environment variables.
.SH EXAMPLE
.P
List the contents of the
.I bin
directory on each host.
.nf
$ sshcmd ls bin < hostlist.txt
.fi
.P
Same, but using
.B --file
option.
.nf
$ sshcmd --file=hostlist.txt ls bin
.fi
.P
Copy war file to tmp directory on all hosts.
.nf
$ sshcmd --remdir=tmp foobar.war < hostlist.txt
.fi
.P
Same but using
.BR sshcpy .
.nf
$ sshcpy foobar.war tmp < hostlist.txt
.fi
.P
Construct the list on the fly.
.nf
$ for i in 01 02 03 04; do echo me@testsrv${i}; done | sshcmd ls
.fi
.P
Execute a python script stored locally.
.nf
$ sshcmd --file=hostlist.txt --input=foo.py python -
.fi
.SH AUTHOR
Michael P. Reilly <arcege@gmail.com>
.SH "SEE ALSO"
.BR ssh (1)
